package cn.wizzer.app.user.modules.service.impl;

import cn.wizzer.app.user.modules.models.RedPacket;
import cn.wizzer.app.user.modules.models.UserLog;
import cn.wizzer.app.user.modules.models.UserSign;
import cn.wizzer.app.user.modules.models.enums.BizTypeEnum;
import cn.wizzer.app.user.modules.models.enums.UserColEnum;
import cn.wizzer.app.user.modules.models.vo.UserSignVO;
import cn.wizzer.app.user.modules.services.RedPacketService;
import cn.wizzer.app.user.modules.services.UserService;
import cn.wizzer.app.user.modules.services.UserSignService;
import cn.wizzer.app.user.modules.services.account.UserAccountRecordService;
import cn.wizzer.app.user.modules.services.account.UserRechargeService;
import cn.wizzer.framework.base.model.enums.BizExceptionEnum;
import cn.wizzer.framework.base.service.BaseServiceImpl;
import cn.wizzer.framework.base.service.CommonDBService;
import cn.wizzer.framework.page.Pagination;
import cn.wizzer.framework.util.Id;
import cn.wizzer.framework.util.Result;
import com.alibaba.dubbo.config.annotation.Service;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.lang.Times;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

@IocBean(args = {"refer:dao"})
@Service(interfaceClass = UserSignService.class)
public class UserSignServiceImpl extends BaseServiceImpl<UserSign> implements UserSignService {
    public UserSignServiceImpl(Dao dao) {
        super(dao);
    }

    @Inject
    private CommonDBService dbService;

    @Inject
    private UserAccountRecordService userAccountRecordService;

    @Inject
    private UserRechargeService userRechargeService;

    @Aop(TransAop.REPEATABLE_READ)
    @Override
    public void sign(String userId) {
        // 查询用户是否有充值过
        if (!userRechargeService.isRecharge(userId)) {
            Result.breakWith(BizExceptionEnum.SIGN_COIN_MUST_HAVE_RECHARGED);
        }
        UserSign last = this.last(userId);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date todayDate = new Date(System.currentTimeMillis());
        String todayStr = simpleDateFormat.format(todayDate);
        UserSign signToday = this.fetchByDate(userId, todayStr);
        if (signToday == null) {
            Date yesterdayDate = new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24);
            String yesterdayStr = simpleDateFormat.format(yesterdayDate);
            UserSign signYesterday = this.fetchByDate(userId, yesterdayStr);
            BigDecimal amount = BigDecimal.ONE;
            if (signYesterday != null) {
                BigDecimal yetAmount = signYesterday.getAmount();
                if (yetAmount.compareTo(new BigDecimal("1")) == 0) {
                    amount = new BigDecimal("2");
                } else if (yetAmount.compareTo(new BigDecimal("2")) == 0) {
                    amount = new BigDecimal("3");
                } else if (yetAmount.compareTo(new BigDecimal("3")) == 0) {
                    amount = new BigDecimal("5");
                } else if (yetAmount.compareTo(new BigDecimal("5")) == 0) {
                    amount = new BigDecimal("8");
                } else if (yetAmount.compareTo(new BigDecimal("8")) == 0) {
                    amount = BigDecimal.ONE;
                }
            }
            UserSign userSign = new UserSign();
            userSign.setAmount(amount);
            // 更新余额
            if (last != null) {
                userSign.setBalance(amount.add(last.getBalance()));
            } else {
                userSign.setBalance(amount);
            }
            userSign.setType("Sign");
            userSign.setUserId(userId);
            userSign.setNo(Id.createOrderNo());
            this.insert(userSign);
        }

    }
    @Aop(TransAop.REPEATABLE_READ)
    @Override
    public void exchange(String userId, BigDecimal amount) {
        // 先求出当前用户的总计分，看够不够
        UserSign last = this.last(userId);
        if (last != null) {
            BigDecimal balance = last.getBalance();
            if (balance.compareTo(amount) < 0) {
                Result.breakWith(BizExceptionEnum.BALL_COIN_NOT_ENOUGH);
            } else {
                UserSign userSign = new UserSign();
                userSign.setType("Exchange");
                userSign.setUserId(userId);
                userSign.setAmount(amount.multiply(new BigDecimal("-1")));
                userSign.setBalance(balance.subtract(amount));
                userSign.setNo(Id.createOrderNo());
                this.insert(userSign);
                // 根据 100 ball coin = 1 USD 换成，插入用户流水
                BigDecimal toUsd = amount.divide(new BigDecimal("100"));
                // 扣掉余额，插入流水
                userAccountRecordService.add("default", userId, toUsd, BizTypeEnum.BALL_COIN_EXCHANGE, userSign.getId(), userSign.getNo());
            }
        } else {
            Result.breakWith(BizExceptionEnum.BALL_COIN_NOT_ENOUGH);
        }
    }

    @Override
    public UserSign  fetchByDate(String userId, String date) {
        StringBuffer sb = new StringBuffer();
        sb.append("select * from user_sign where userId='");
        sb.append(userId).append("' ");
        sb.append(" and type='Sign'");
        sb.append(" and date_format(from_unixtime(ctAt),'%Y-%m-%d')='");
        sb.append(date).append("'");
        return dbService.fetchSql(UserSign.class, sb.toString());
    }

    @Override
    public List<UserSign> list5(String userId, String type) {
        StringBuffer sb = new StringBuffer();
        sb.append("select * from user_sign where userId='");
        sb.append(userId).append("' and type='Sign' order by ctAt desc limit 5");
        return dbService.list(UserSign.class, sb.toString());
    }

    @Override
    public UserSign last(String userId) {
        StringBuffer sb = new StringBuffer();
        sb.append("select * from user_sign where userId='");
        sb.append(userId).append("' order by ctAt desc limit 1");
        return dbService.fetchSql(UserSign.class, sb.toString());
    }

    @Override
    public UserSignVO querySign(String userId) {

        UserSignVO vo = new UserSignVO();
        vo.setUserId(userId);
        // 查出最近一条
        UserSign last = this.last(userId);
        if (last == null) {
            vo.setBalance(BigDecimal.ZERO);
            vo.setTodayFlag(false);
            vo.setDayTh(0);
            return vo;
        } else {
            vo.setBalance(last.getBalance());
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            Date todayDate = new Date(System.currentTimeMillis());
            String todayStr = simpleDateFormat.format(todayDate);
            // 查出今日签到
            UserSign signToday = this.fetchByDate(userId, todayStr);
            // 如果今天还未签到则
            if (signToday != null) {
                vo.setTodayFlag(true);
                BigDecimal todayAmount = signToday.getAmount();
                if (todayAmount.compareTo(new BigDecimal("1")) == 0) {
                    vo.setDayTh(1);
                } else if (todayAmount.compareTo(new BigDecimal("2")) == 0) {
                    vo.setDayTh(2);
                } else if (todayAmount.compareTo(new BigDecimal("3")) == 0) {
                    vo.setDayTh(3);
                } else if (todayAmount.compareTo(new BigDecimal("5")) == 0) {
                    vo.setDayTh(4);
                } else if (todayAmount.compareTo(new BigDecimal("8")) == 0) {
                    vo.setDayTh(5);
                }
            } else {
                vo.setTodayFlag(false);
                Date yesterdayDate = new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24);
                String yesterdayStr = simpleDateFormat.format(yesterdayDate);
                UserSign signYesterday = this.fetchByDate(userId, yesterdayStr);
                if (signYesterday != null) {
                    BigDecimal yetAmount = signYesterday.getAmount();
                    if (yetAmount.compareTo(new BigDecimal("1")) == 0) {
                        vo.setDayTh(1);
                    } else if (yetAmount.compareTo(new BigDecimal("2")) == 0) {
                        vo.setDayTh(2);
                    } else if (yetAmount.compareTo(new BigDecimal("3")) == 0) {
                        vo.setDayTh(3);
                    } else if (yetAmount.compareTo(new BigDecimal("5")) == 0) {
                        vo.setDayTh(4);
                    } else if (yetAmount.compareTo(new BigDecimal("8")) == 0) {
                        vo.setDayTh(5);
                    }
                }
            }
            return vo;
        }
    }

    @Override
    public Pagination pageList(String userId, Integer pageNumber, Integer pageSize) {
        StringBuffer sb = new StringBuffer();
        sb.append("select * from user_sign where userId='");
        sb.append(userId).append("' order by ctAt desc ");
        return dbService.listPage(UserSign.class, pageNumber, pageSize, sb.toString());
    }

    @Override
    public Pagination listPage(String conditionData, String type, String keyword, String[] searchDate, int pageNumber, int pageSize) {
        Sql sql = Sqls.create("SELECT us.*,u.nickName,u.userName,u.phone")
                .appendSourceSql("FROM user_sign AS us left join user AS u ON us.userId = u.id $condition");
        Cnd cnd = Cnd.NEW();
        if (Strings.isNotBlank(conditionData)) {
            String[] split = conditionData.split(",");
            for (String col : split) {
                String colName = UserColEnum.getValByName(col);
                if (Strings.isNotBlank(colName)) {
                    // 默认不显示游客、内部账号
                    cnd.and("u." + colName, "=", 0);
                }
            }
        }
        if (Strings.isNotBlank(type)) {
            cnd.and("us.type", "=", type);
        }
        // 根据用户信息搜索
        if (Strings.isNotBlank(keyword)) {
            keyword = "%" + keyword + "%";
            cnd.and(Cnd.exps("u.nickName", "LIKE", keyword)
                    .or("u.userName", "LIKE", keyword)
                    .or("u.phone", "LIKE", keyword)
            );
        }
        // 根据日期搜索
        if (null != searchDate && searchDate.length != 0) {
            cnd.and("us.ctAt", ">=", Times.d2TS(Times.D(searchDate[0])));
            cnd.and("us.ctAt", "<=", Times.d2TS(Times.D(searchDate[1])));
        }
        sql.setCondition(cnd);
        sql.appendSourceSql("ORDER BY us.ctAt DESC");
        return dbService.listPage(UserSignVO.class, pageNumber, pageSize, sql.toString());
    }

    @Override
    public BigDecimal searchSum(String conditionData, String type, String searchKeyword, String[] searchDate) {
        StringBuffer sb = new StringBuffer();
        sb.append("select IFNULL(sum(r.amount), 0) from user_sign r ");
        sb.append(" left join user u on u.id = r.userId ");
        sb.append(" where 1=1");
        if (Strings.isNotBlank(conditionData)) {
            String[] split = conditionData.split(",");
            for (String col : split) {
                String colName = UserColEnum.getValByName(col);
                if (Strings.isNotBlank(colName)) {
                    // 默认不显示游客、内部账号
                    sb.append(" and u.").append(colName).append(" = 0");
                }
            }
        }
        if (Strings.isNotBlank(searchKeyword)) {
            sb.append(" and ( u.nickName like '%").append(searchKeyword).append("%'");
            sb.append(" or u.phone like '%").append(searchKeyword).append("%'");
            sb.append(" or u.userName like '%").append(searchKeyword).append("%' ");
            sb.append(" or r.no like '%").append(searchKeyword).append("%' )");
        }
        if (searchDate != null && searchDate.length > 0) {
            sb.append(" and r.ctAt >=").append(Times.d2TS(Times.D(searchDate[0])));
            sb.append(" and r.ctAt <=").append(Times.d2TS(Times.D(searchDate[1])));
        }
        if (Strings.isNotBlank(type)) {
            sb.append(" and r.type = '").append(type).append("'");
        }
        Sql sql = Sqls.create(sb.toString());
        sql.setCallback(Sqls.callback.str());
        this.dao().execute(sql);
        return new BigDecimal(sql.getString()).setScale(6, BigDecimal.ROUND_DOWN);
    }
}
